/**
 * 
 */
package com.vision.core.sv.serv.rpc.handler;

import java.sql.Timestamp;

import net.customware.gwt.dispatch.server.ExecutionContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.vision.core.cm.action.CreateUserAction;
import com.vision.core.cm.action.CreateUserResult;
import com.vision.core.cm.data.AdminPermissions;
import com.vision.core.cm.db.data.User;
import com.vision.core.cm.db.data.User.UserStatus;
import com.vision.core.cm.exception.DispatchException;
import com.vision.core.sv.security.Encrypt;
import com.vision.core.sv.serv.rpc.UserServiceImpl;

/**
 * Command pattern implementation of the 'Create User' use-case using GWT-Dispatch.
 * 
 * The code being executed is the same as the code in {@link UserServiceImpl#create(User)}.
 * 
 * @author Mark
 *
 */
@Component
public class CreateUserHandler extends UserHandler<CreateUserAction, CreateUserResult> {
	
	private static final Logger log = LoggerFactory.getLogger(CreateUserHandler.class);
	
	@Override
	public Class<CreateUserAction> getActionType() {
		return CreateUserAction.class;
	}

	@Transactional // Ensures that all database operations are done as one transaction
	@Override
	public CreateUserResult execute(CreateUserAction action, ExecutionContext context) throws DispatchException {
		checkPermissions(AdminPermissions.CreateUser);
		
		User user = action.getUser();
		
		checkUsername(user.getUsername());
		
		String cleanedUsername = user.getUsername().toLowerCase().trim();
		user.setUsername(cleanedUsername);
		
		ensureNonExisting(user);
		
		user.setPassword(Encrypt.encode(user.getPassword()));
		user.setDateCreated(new Timestamp(System.currentTimeMillis()));
		user.setStatus(UserStatus.ACTIVE);
		
		log.debug("Creating user: {}", user.getUsername());
		
		User result = dataManager.create(user);
		
		// Log the creation event
		logCreate(result);
		
		// TODO Strip out the user's password before sending back to client.
		// Stripping out must be done outside Spring's transaction context since
		// the transaction must complete.
		
		return new CreateUserResult(result);
	}
	
}